如何在發佈 ASP.NET Core 網站時自動套用 Shadow Copying 設定
TLDR
- Shadow Copying 可解決 ASP.NET Core 執行時 DLL 被鎖定導致無法更新的問題。
- 透過在專案根目錄預置
web.config,發佈時會自動合併設定,無需手動修改伺服器檔案。 - 建議使用
dotnet publish指令結合web.config預置,實現 CI/CD 自動化部署。 - Hosting Bundle 7.0+ 使用
enableShadowCopy;6.0 版本則需使用experimentalEnableShadowCopy。 - Shadow Copying 機制會自動清理舊資料夾,並非版本管理工具,不應依賴其保留舊版本。
- 升級 .NET 版本後務必手動清理 Shadow Copying 資料夾,否則會觸發 500.30 錯誤。
- 應避免在應用程式目錄內寫入檔案或 Log,以免頻繁觸發不必要的應用程式重啟。
解決發佈時 DLL 鎖定問題
什麼情況下會遇到這個問題: 當 Web 應用程式正在運行時,IIS 會鎖定相關 DLL 檔案,導致部署新版本時無法覆蓋檔案,必須手動停止應用程式集區。
Shadow Copying(陰影複製)機制會將應用程式檔案複製到暫存位置執行,從而釋放原始部署目錄的鎖定狀態。傳統做法是手動修改伺服器上的 web.config,但這不適合 CI/CD 流程。
最佳實踐是在專案根目錄預先建立 web.config,發佈時系統會自動將其作為基礎進行合併。
設定範例
在專案根目錄的 web.config 中加入 handlerSettings:
xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebApi.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
<handlerSettings>
<handlerSetting name="enableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory" value="../ShadowCopy/" />
</handlerSettings>
</aspNetCore>
</system.webServer>
</location>
</configuration>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
若需同時設定環境變數(如 ASPNETCORE_ENVIRONMENT),可直接在 .pubxml 中設定,發佈後會自動合併至 web.config:
xml
<EnvironmentName>Staging</EnvironmentName>1
執行發佈指令:
bash
dotnet publish -c Release -p:EnvironmentName=Staging1
版本差異
- Hosting Bundle 7.0.0 以上:使用
enableShadowCopy參數。 - Hosting Bundle 6.0.0:使用
experimentalEnableShadowCopy參數。
關於 Shadow Copying 的資料夾管理機制
什麼情況下會遇到這個問題: 當開發者誤以為 Shadow Copying 會自動維護多個版本供回滾使用時。
根據 AspNetCoreModuleV2 原始碼分析,Shadow Copying 的設計並非版本管理工具。當系統選定一個新的流水號資料夾作為執行路徑後,會啟動執行緒刪除該目錄下所有其他的資料夾。若發現目錄內有多個資料夾並存,通常是清理執行緒尚未完成,或是舊檔案被鎖定導致刪除失敗。
注意事項
- 升級 .NET 版本:升級後必須手動刪除舊的 Shadow Copying 資料夾,否則會導致 IIS 出現 500.30 錯誤,事件檢視器會顯示
directory_iterator找不到路徑的異常。 - 避免寫入檔案:應避免在應用程式目錄中寫入檔案或 Log,否則每次檔案異動都可能觸發 Shadow Copying 機制,導致應用程式不必要的重啟。
異動歷程
- 初版文件建立。
- 補充升級 .NET 版本造成 Shadow Copying 異常。
- 補充使用 Shadow Copying 時需避免在應用程式目錄寫入檔案的注意事項。
- 補充 Shadow Copying 資料夾管理機制的常見誤解與源碼說明。